\documentclass{article}

\usepackage[brazil]{babel}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{sbc-template}

\title{Relatório de TGA sobre Gerência de Processos}
\author{Wanderson Henrique Camargo Rosa\inst{1}}
\address{Laboratório de Sistemas Operacionais --- 2011/2\\Centro de Ciências
Exatas e Tecnológicas\\Universidade do Vale do Rio dos Sinos --- UNISINOS}

\begin{document}

\maketitle{}

\section{Introdução}

Este documento visa apresentar anotações e criar um relatório parcial das
atividades propostas pela disciplina de Laboratório de Sistemas Operacionais,
semestre de 2011/2, sobre programação Gerência de Processos utilizando Linguagem
de Programação Shellscript e C.

Na proposta do trabalho, foi apresentado um código-fonte de um programa descrito
em Shellscript com alguns problemas de sintaxe e codificação, sendo que existe a
necessidade de organização de código, refatoração e documentação em blocos de
código, visando estudos sobre o algoritmo implementado.

\section{Análise Geral}

O \textit{script} atual busca criar um novo método para execução de
\textit{downloads} sobre arquivos informados em linha de comando. Recebendo como
parâmetro opcional \texttt{-t}, podemos esperar a cópia do arquivo remoto pela
quantidade de segundos informada. Após este parâmetro, podemos fornecer uma
lista de arquivos para download, processados pelo \textit{script}.

Utilizando um laço de repetição, o bloco principal do programa desloca os
parâmetros para esquerda, afim de fornecê-lo ao programa real que efetua o
\textit{download} dos arquivos, neste caso, o \texttt{wget}. Este, é
inicializado com o parâmetro \texttt{-c} que tenta continuar um
\textit{download} pausado anteriormente.

Ainda neste \textit{script}, existem duas funções implementadas, onde a primeira
utiliza o programa para executar o \textit{download} sem tempo de término,
chamado de \textit{timeout}. A segunda trabalha com \textit{timeout} simulado,
utilizando uma espera de execução no sistema operacional do processo que é
enviado ao \textit{background}. Quando este \textit{timeout} é finalizado, o
programa de \textit{download} é finalizado através de um sinal \texttt{KILL}.

Estas funções são chamadas para cada arquivo informado na linha de comando. A
saída de erro do \texttt{KILL} é redirecionada para o escritor especial que
ignora as informações enviadas \texttt{/dev/null}. Já o programa que executa o
\textit{download} apresenta normalmente a sua saída. Ao final, são apresentados
os resultados na saída padrão, efetuando a soma da quantidade de
\textit{downloads} executados e quantos foram finalizados com sucesso.

\section{Tópicos}

Houve a necessidade de criação de um arquivo com o nome de
\texttt{downloader.sh} para armazenar o código-fonte informado pela disciplina.
Para que o arquivo receba credenciais para execução, houve a necessidade de
execução do comando \texttt{chmod +x downloader.sh} ou chamar diretamente o
interpretador de comandos com o comando \texttt{bash downloader.sh}.

O programa atual não possui a linha de \textit{hashbang} completo, sendo
necessária sua modificação para \texttt{\#!/bin/bash}.

As variáveis devem ser inicializadas com o sinal de atribuição como sufixo e
adjacente, sem espaços entre ambos os \textit{tokens}, caso contrário a
atribuição desejada não irá funcionar. Também existe o caso em que variáveis
recebem valores e o sinal de atribuição está sendo separado por um espaço, não
categorizando somente as inicializações.

O código de término de execução com falhas deve ser diferente de zero;
necessário porque o sistema operacional espera um inteiro com valor 0 para que o
processo informe sucesso em sua execução. Já o código de sucesso também deve ser
alterado, buscando apresentar um valor conciso ao sistema operacional sobre o
estado do processamento.

O nome da variável de sucesso está sendo inicializado com identificador
diferente de todos os outros pontos do código-fonte, gerando uma inconsistência
na execução correta, onde outros pontos do programa irão utilizar variáveis não
inicializadas. Isto também está acontecendo na apresentação de resultado com
falha, onde o conteúdo da variável não é expandido.

A função \texttt{print\_info} possui retorno que não está sendo acessado
corretamente através da expansão de variável, não acessando o valor de sucesso
armazenado no conteúdo.

Necessária implementação da divisão entre os dois blocos condicionais do
\texttt{case}, buscando não executar os dois comandos em cascata e saindo do
bloco. Neste caso, precisamos que o \texttt{case} não execute os próximos
comandos, portanto é preciso adicionar dois pontos-e-vírgula \texttt{(;;)}
para escapar do bloco condicional.

Quando existe a verificação da quantidade de parâmetros que foram informados ao
\textit{script}, existe a necessidade de utilizar os operadores de comparação de
texto, onde o interpretador de comandos espera que o segundo parâmetro seja um
arquivo para redirecionamento da entrada padrão.

O número para acesso dos parâmetros dentro da função \texttt{print\_info} está
errado, não informando corretamente o número de \textit{downloads} executados
com sucesso, muito menos executando o somatório de \textit{downloads}. Aplicada
documentação mais completa ao \textit{script}, com descrição de funcionalidades
executadas.

A primeira função efetua o \textit{download} dos arquivos sem \textit{timeout};
logo o sistema operacional espera até que a cópia do arquivo remoto seja
finalizada. Podemos utilizar o parâmetro opcional \texttt{-t} na primeira
função, porém ela não é manipulada dentro de seu escopo. Para corrigir o seu
problema de execução, somente foi adicionado o parâmetro de \textit{timeout} na
chamada para execução, tendo em vista que outros pontos do sistema podem
utilizar a mesma função.

\section{Código-Fonte Shellscript Modificado}

\begin{small}
\begin{verbatim}
\include{../trabalho01/downloader.sh}
\end{verbatim}
\end{small}

\section{Tradução do Código}

Conforme solicitado na terceira atividade do Trabalho, devemos implementar um
programa utilizando a linguagem C que execute as mesmas tarefas do
\textit{script} acima. Este programa deve utilizar gerenciamento de processos.

Após análise simples, podemos ver que toda a lógica de execução está
desenvolvida no código do \textit{script} acima e que somente precisamos
utilizar as instruções em C semelhantes de cada comando acima.

Primeiramente, não foram utilizadas variáveis globais dentro do código,
buscando trabalhar sobre o escopo local de cada bloco de comandos. Informações
que são utilizadas em muitas partes e não modificam seus valores foram aplicadas
como definições de pré-compilador.

As assinaturas de funções foram criadas anteriormente ao método principal, sem
nomes de parâmetros e somente seus tipos. Todas as funções utilizadas no
\textit{script} também foram criadas neste código, com parâmetros adicionais
tendo em vista que as variáveis globais foram removidas.

Para trabalhar com a chamada de funções selecionadas em tempo de execução como
no \textit{script} que executa o conteúdo de uma variável, o código em C utiliza
ponteiros para funções, trabalhando de forma semelhante. Os ponteiros para
funções devem apontar para estruturas que possuem a mesma assinatura,
trabalhando como um tipo de dado; caso isto não seja programado de forma
correta, o compilador gera um aviso de tipos de funções diferentes ao tipo de
ponteiro utilizado.

A segunda função que executa o \textit{download} chamada \texttt{exec\_dl2}
divide o processo atual, gerando um processo filho que executa a cópia da
informação do endereço fornecido. Já o processo pai espera pelo tempo descrito e
finaliza o processo filho ao final do \textit{timeout} informado.

\section{Código-Fonte C}

\begin{small}
\begin{verbatim}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>

#define DOWNLOADER "wget"
#define DL_OPTIONS "-c"
#define TRUE 1
#define RESULT_FAILURE 15
#define TIMEOUT_OFF -1

int exec_dl1(int,char*);
int exec_dl2(int,char*);
void print_info(int,int,int);

int main(int argc, char* argv[]) {
    // Auxiliar para Contagem de URL
    // Posição de Argumentos para URL de Download Atual
    int counter = 1;
    // Auxiliar para Verificação de Timeout
    int timeout = TIMEOUT_OFF;

    // Verifica a Quantidade de Parâmetros Informados
    if (argc < 2) { // Contagem Adicional de Parâmetros +1
        printf("%s: Parâmetros Insuficientes\n", argv[0]);
        printf("Uso: %s [ -t timeout ] urls...\n", argv[0]);
        // Resultado do Término
        exit(RESULT_FAILURE);
    }

    // Verifica Segundo Parâmetro: Tempo de Espera
    if (strcmp(argv[1], "-t") == 0) { // Parâmetro Informado
        // Utilização de Timeout Informado
        timeout = atoi(argv[2]);
        // Deslocamento de Posição de Parâmetros
        counter = counter + 2;
    }

    // Número de Downloads com Sucesso: ns
    // Número de Downloads com Falha  : nf
    int ns = 0; int nf = 0;
    // Variáveis Auxiliares do Laço de Repetição
    char* url; int result;
    int (*exec_dl)(int,char*);
    while (TRUE) { // Laço de Repetição Infinito
        if (counter + 1 > argc) { // Existem Downloads para Execução?
            break; // Contador Acima de Quantidade de Argumentos
        } else {
            url = argv[counter]; // Capturar URL Informada
            counter = counter + 1; // Deslocar Posição do Parâmetro
        }
        // Bloco Condicional
        switch (timeout) { // Verificar Tipo de Timeout
            case TIMEOUT_OFF: // Timeout -1 Descartável na Função
                exec_dl = &exec_dl1;
                break;
            default:
                exec_dl = &exec_dl2;
        }
        // Executar Download Selecionado
        result = exec_dl(timeout, url);
        // Verificação dos Resultados
        if (result == 0) {
            ns = ns + 1; // Successo
        } else {
            nf = nf + 1; // Falha
        }
    }

    // Apresentação de Resultados
    print_info(ns, nf, timeout);

    return EXIT_SUCCESS;
}

/**
 * Execução de Comando de Downloader sem Timeout
 * @param timeout Timeout de Execução
 * @param url Endereço para Download
 * @return Resultado do Término da Execução
 */
int exec_dl1(int timeout, char* url) {
    execl("/usr/bin/wget", DOWNLOADER, DL_OPTIONS, url, NULL);
    return EXIT_SUCCESS;
}

/**
 * Execução de Comando de Downloader com Timeout
 * @param timeout Timeout de Execução
 * @param url Endereço para Download
 * @return Resultado do Término da Execução
 */
int exec_dl2(int timeout, char* url) {
    // Capturar o PID e Esperar o Tempo Solicitado
    // Conectar a Saída de Erro na Saída Padrão
    // Terminar o Processo de Forma "Elegante"
    pid_t child = fork(); // PID do Filho
    if (child) { // Processo Pai != 0
        sleep(timeout); // Tempo de Espera
        kill(child, SIGKILL); // Término do Processo Filho
    } else { // Processo Filho
        // Execução do Download em Background
        execl("/usr/bin/wget", DOWNLOADER, DL_OPTIONS, url, NULL);
        // Finalizar Execução do Filho
        exit(EXIT_SUCCESS); // Término com Sucesso
    }
    return EXIT_SUCCESS;
}

/**
 * Impressão de Informações
 * @param ns Número de Execuções com Sucesso
 * @param nf Número de Execuções com Falha
 */
void print_info(int ns, int nf, int timeout) {
    printf("Programa de Download Utilizado: %s %s\n", DOWNLOADER, DL_OPTIONS);
    // Bloco Condicional
    if (timeout != TIMEOUT_OFF) {
        // Entra Caso Timeout é Válido
        printf("Timeout de Execução: %d\n", timeout);
    }
    printf("Número total de downloads executados: %d\n", ns + nf);
    printf("Número de downloads executados com sucesso: %d\n", ns);
}

\end{verbatim}
\end{small}

\end{document}

